package org.apache.ibatis.common.reflection.property;

import org.apache.ibatis.common.reflection.Reflector;

import java.lang.reflect.Field;

/**
 * @Name PropertyCopier
 * @Description: 属性拷贝器
 * 描述信息：该类主要用来完成对象属性的复制操作，即将一个对象的属性复制到另一个对象中的操作。
 * @Version v1.0.0
 * @Author: lichao
 * @Date: 2024-04-25 15:33:21
 **/
public class PropertyCopier {

    private PropertyCopier() {
    }

    /**
     * 拷贝属性
     * 注意：该方法无法对继承得来的属性进行拷贝，因为通过反射技术获取到属性不包含继承属性。
     *
     * @param type            目标对象类型
     * @param sourceBean      提供属性值的对象
     * @param destinationBean 被写入新属性值的对象
     * @version v1.0.0
     * @author lichao
     * @date 2024-04-25 15:35:56
     */
    public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
        // 目标类
        Class<?> targetClass = type;
        while (targetClass != null) {
            final Field[] fields = targetClass.getDeclaredFields();
            for (Field field : fields) {
                try {
                    try {
                        // 1. 直接通过反射拷贝属性的值
                        field.set(destinationBean, field.get(sourceBean));
                    } catch (IllegalAccessException e) {
                        // 如果发生异常，则修改目标对象属性的访问权限后再次尝试拷贝属性值
                        if (Reflector.canControlMemberAccessible()) {
                            field.setAccessible(true);
                            field.set(destinationBean, field.get(sourceBean));
                        } else {
                            throw e;
                        }
                    }
                } catch (Exception e) {
                    // 只有在拷贝 final 属性时才会报错，这里什么也不做，直接忽略即可
                }
            }
            targetClass = targetClass.getSuperclass();
        }
    }


}

